/*****************************************************************
                     fpc_save.c
*******************************************************************/
#include "../clam/clam.h"
#include <fcntl.h>
#ifdef ALPHA
#include "sex.h"
#endif
#define SEEK_SET 0
#include <time.h>
#include <pwd.h>
#include <float.h>
#include <sys/param.h>
#include <errno.h>
#include "mtp.h"
#include "bss.h"
#include "seq.h"

#define BUFSZ 120

/*efriedr*/
#define graphQuery messQuery

extern char projectname[80];
extern BOOL update;
extern char timestamp[255];
extern BOOL okaytowrite,writeaccess;
extern int defaultflag;
extern int Zbatch_flag, Zkill_seq;

void savefppdata(), ZsaveCpM(), ZsaveBuild();
void displaymess(char *text), getdatehead();
int spaceOnly(char *tmp);

/***********************************************************
               DEF: save_fpc
************************************************************/
int save_fpc()
{
  FILE *fpout;
  CLONE *clone;
  int i, j, savefpp=1;
  struct markertop *topmarkerptr;
  struct marker *markerptr;
  struct remark *pointer;
  struct marker *marker;
  struct fpdata *temp1;
  char buf[MAXPATHLEN*3],file[MAXPATHLEN], out2[120], tdate[255];
  int nbands;
  struct passwd *uinfo;
  char str1[15], str2[15];
  char tmpDQ[10];
  struct file_list* pfiles;
  char gen_names[20];

  if (strlen(fileName) == 0) {
     displaymess("ERROR - no file name");
     return 0;
  }
  if(okaytowrite) {
     if(strlen(dirName)>0) sprintf(file, "%s/%s.fpc", dirName, fileName);
     else sprintf(file,"%s.fpc",fileName);

     errno = 0;
     if ((fpout = fopen(file,"r+")) != NULL) {
       fclose(fpout);
       sprintf(buf,"mv %s %s.backup", file, file);
       system(buf); /* mode gets changed on mv in nightly fpc cronjob */
       sprintf(buf,"chmod -f 664 %s.backup", file);
       system(buf);
     }
     else { /* 27 jul - CHG having weird permission problems */
       printf("Cannot open r+ %d.\n", errno);
       /*efriedr*/
       /*printf("FPC is moving the file to %s.fpc.backup and will try again.\n", file);*/
       printf("FPC is moving the file to %s.backup and will try again.\n", file);

#ifdef AGI
       system("groups");
       printf("Email these messages to cari.\n", file);
#endif
       sprintf(buf,"mv %s %s.backup", file, file);
       system(buf);
       if ((fpout = fopen(file,"w")) != NULL) fclose(fpout);
       else {
		 /* sness */
         /* printf("Cannot open for write. Check permissions. \n", file); */
          printf("Cannot %s open for write. Check permissions. \n", file);
          okaytowrite=FALSE;
       }
     }
  }
  if (!okaytowrite){
      if (Zbatch_flag) {
        fprintf(stderr,"File is locked. Cannot save.\n");
        return -1;
      }
      uinfo = (struct passwd *) getpwuid((uid_t) geteuid());
      if (uinfo == NULL) {
         printf("**** Cannot get user id\n");
         //return -1;
		uinfo = (struct passwd*)malloc(sizeof(struct passwd));
		uinfo->pw_name = strdup("unknown");
      }
      sprintf(buf,
 "The project is unavailable for writing, Do you wish to save it as %s-%s.fpc?",
                 fileName, uinfo->pw_name);
	  /* sness */
      /*if(!graphQuery(buf)) return -1; */
      if(!messQuery(buf)) return -1;
      savefpp=0;

      if(strlen(dirName)>0)
           sprintf(file, "%s/%s-%s.fpc", dirName, fileName, uinfo->pw_name);
      else sprintf(file,"%s-%s.fpc",fileName, uinfo->pw_name);
  }
  if ((fpout = fopen(file,"w"))!=NULL) {
    fprintf(stderr,"Saving File %s...", file);
    fflush(stderr); /* cari - 12/24/03 - so when batch, write immediately */
  }
  else {
    fprintf(stderr,"*** Cannot Write File %s\n", file);
    return -1;
  }

  if(bands) nbands = arrayMax(bands);
  else nbands = tot_bands;

            /** fpc_load reads these lines; so if change, change in fpc_load also **/
  fprintf (fpout, "// fpc project %s\n", fileName) ;
  getdatehead(tdate);
  fprintf (fpout, "// %s\n", tdate) ;
  sprintf (timestamp,"// %s\n", tdate) ;

  gen_names[0] = 0;
  if (Proj.generic_grpnames)
  {
    sprintf(gen_names,"generic_grpnames");
  }
  for (i=j=0; i<max_contig; i++) if (contigs[i].count>0) j++;
  fprintf (fpout, "// Contigs %d  Clones %d  Markers %d  Bands %d\n",
          j, arrayMax(acedata), arrayMax(markerdata), nbands) ;
  if (Proj.mapname[0]!='\0')
       fprintf (fpout, "// Framework %s Label %s Abbrev %s %s Genome %.0f AvgBand %d  AvgInsert %d\n",
               Proj.mapname, Proj.anchor_label, Proj.label_abbrev, gen_names, Proj.genomesize,
               Proj.avgbandsize, Proj.avginsertsize);
  else
       fprintf (fpout, "// Genome %20.0f  AvgBand %d  AvgInsert %d\n",
               Proj.genomesize, Proj.avgbandsize, Proj.avginsertsize);
  if (Proj.uncfile[0] != '\0') fprintf(fpout, "// Unc %s\n",Proj.uncfile);
  if (Proj.filterfile[0] != '\0') fprintf(fpout,"// Vector %s\n",Proj.filterfile);

/* Configure line */
  if (Proj.variable) fprintf(fpout, "// Configure %d  Variable ",defaultflag);
  else fprintf(fpout, "// Configure %d ",defaultflag);
  if (Proj.eq2==1) fprintf(fpout, "EQ2 ");
  else if (Proj.eq2==2) fprintf(fpout, "EQ3 ");
  fprintf(fpout,
"Tol %d Cut %.0e Apx %3.3f Gel %d End %d SeqEnd %d Kill %d Bad %d Best %d Log %d Std %d Page %d Match %d %s\n",
    Pz.tol, Pz.cutFlt,  Pz.burFlt, Proj.gel_len, Pz.fromendInt, Pz.seq_fromendInt, Pz.killInt,
    Pz.diffInt, Pz.bestInt, Pz.logFlag, Pz.stdFlag, Proj.default_page_size, Pz.mergeMatches, Pz.fp_class == AGAROSE ? "agarose" : "hicf");

  ZsaveCpM(out2); fprintf(fpout, "%s",out2);
  ZsaveBuild(out2); fprintf(fpout, "%s",out2);

     /* CAS 15feb04 - add precompute and UseSeq, remove AutoRemark */
  out2[0] = '\0';
  if (Pz.precompute) strcpy (out2, "Precompute");
  if (Zkill_seq) strcat (out2, " UseSeq");

  if (0 == Pz.DQusePct) {
    sprintf(tmpDQ,"%d",Pz.DQnumq);
  }
  else {
    sprintf(tmpDQ,"%d%%",Pz.DQnumq);
  }
  fprintf(fpout,"// Clip(%d %d) MinMax(%d %d) %s DQer(%s,%d)\n",
       Proj.MinClip, Proj.MaxClip, Pz.minVal, Pz.maxVal, out2,
        tmpDQ, Pz.DQstep);
  mtp_save_configuration(fpout);
  fprintf(fpout,"// SEQ_min_clones %d SEQ_min_ctgs %d SEQ_winsize %d SEQ_topn %d SEQ_endmatch %d\n",SeqProps.min_clones,
                        SeqProps.min_ctgs,SeqProps.window_size,SeqProps.top_n,SeqProps.endmatch_check);

          /* write clones */
  for(i=0;i<arrayMax(acedata);i++){
    clone = arrp(acedata,i,CLONE);
    fprintf(fpout,"  \n%s : \"%s\"\n",clonetype[clone->class],clone->clone);

    if(clone->ctg !=0){
      fprintf(fpout,"Map \"ctg%d\" Ends Left %d.000\n",clone->ctg,clone->x);
      if (clone->ibc)
        fprintf(fpout,"Map \"ctg%d\" Ends Right %d.000 Oldctg %d CpM\n",
                clone->ctg,clone->y, clone->oldctg);
      else
        fprintf(fpout,"Map \"ctg%d\" Ends Right %d.000 Oldctg %d\n",
                clone->ctg,clone->y, clone->oldctg);
    }
    temp1 = clone->fp;
    while(temp1 != NULL){
      if(temp1->fpchar[0] != ' ')
	fprintf(fpout,"Fp_number \"%s\"\n",temp1->fpchar);
      fprintf(fpout,"Gel_number    %s\n",temp1->gelname);
      fprintf(fpout,"Bands  %d %d\n",temp1->b1,temp1->b2);
      temp1= temp1->next;
    }
    if(clone->mattype > PSPARENT){ /* i.e. if its a match */
      if(clone->mattype & EXACT )
	fprintf (fpout,"Exact_match_to_cosmid \"%s\"\n", clone->match) ;
      else if(clone->mattype & APPROX)
	fprintf (fpout,"Approximate_match_to_cosmid \"%s\"\n", clone->match) ;
      else if(clone->mattype & PSEUDO)
	fprintf (fpout,"Pseudo_match_to_cosmid \"%s\"\n", clone->match) ;

    }
    pointer=clone->remark;
    while(pointer!=NULL){
	fprintf(fpout,"Remark \"%s\"\n", pointer->message) ;
      pointer = pointer->next;
    }

    if(clone->seqstat > 0) /* ADD 19mar99 */
      fprintf(fpout,"Shotgun %s %s\n",seqtype[clone->seqtype], seqstat[clone->seqstat]);

    if(clone->marker !=NULL){
      topmarkerptr = clone->marker;
      while(topmarkerptr != NULL){ /*for each marker */
	markerptr = arrp(markerdata,topmarkerptr->markerindex,MARKER);
	if(markerptr != NULL){
          if (topmarkerptr->new==1) strcpy(out2, "New");
          else if (topmarkerptr->new==2) strcpy(out2, "CpM");
          else out2[0]='\0';
	  if(topmarkerptr->weak)
	    fprintf(fpout,"Positive_%s_weak \"%s\" %s\n",
               markertype[markerptr->type],markerptr->marker, out2);
	  else
	    fprintf(fpout,"Positive_%s \"%s\" %s\n",markertype[markerptr->type],
               markerptr->marker, out2);
	}
	topmarkerptr = topmarkerptr->nextmarker;
      }
    }
    pointer=clone->fp_remark;
    while(pointer!=NULL){
	fprintf(fpout,"Fpc_remark \"%s\"\n", pointer->message) ;
      pointer = pointer->next;
    }
   fprintf(fpout,"Creation_date %d %d %d %d %d \n",clone->creation_date.year,
         clone->creation_date.month, clone->creation_date.day,
         clone->creation_date.hour,clone->creation_date.minute);
   fprintf(fpout,"Modified_date %d %d %d %d %d \n",
          clone->modified_date.year,clone->modified_date.month,
	  clone->modified_date.day,clone->modified_date.hour,
          clone->modified_date.minute);
  }

  fprintf(fpout,"\nMarkerdata\n\n");

  for(i=0;i<arrayMax(markerdata);i++){
    marker = arrp(markerdata,i,MARKER);
    fprintf(fpout,"Marker_%s : \"%s\"\n",markertype[marker->type],marker->marker);

    if(marker->anchor){
      if(marker->anchor_bin[0] != '\0'){
	fprintf(fpout,"Anchor_bin \"%s\"\n",marker->anchor_bin);
      }
      if(marker->frame_type==FRAME)
        fprintf(fpout,"Anchor_pos %7.1f F\n",marker->anchor_pos);
      else
        fprintf(fpout,"Anchor_pos %7.1f P\n",marker->anchor_pos);
    }

    /*fred 11/6/02 -- add marker remarks*/
    pointer=marker->remark;
    while(pointer!=NULL){
	fprintf(fpout,"Remark \"%s\"\n", pointer->message) ;
      pointer = pointer->next;
    }

    /*if(marker->anchor == TRUE) fprintf(fpout,"anchor\n");*/
    fprintf(fpout,"Creation_date %d %d %d %d %d \n",
           marker->creation_date.year,marker->creation_date.month,
	   marker->creation_date.day,marker->creation_date.hour,
           marker->creation_date.minute);
    fprintf(fpout,"Modified_date %d %d %d %d %d \n",
              marker->modified_date.year,marker->modified_date.month,
	      marker->modified_date.day,marker->modified_date.hour,
              marker->modified_date.minute);
    fprintf(fpout,"\n");
  }

  fprintf(fpout,"\nContigdata %d\n\n", max_contig);

  for (i=0; i<=max_contig; i++) {
    char str[10];
    if (contigs[i].count==0) continue;
    if (contigs[i].approxQs) strcpy(str,"ApproxQs");
    else str[0] = '\0';
    fprintf(fpout,"Ctg%d %d/%d/%d %d:%d %s%c %d # High %d Avg %d Low %d %s\n", i,
      contigs[i].ctgdate.day,contigs[i].ctgdate.month, contigs[i].ctgdate.year,
      contigs[i].ctgdate.hour, contigs[i].ctgdate.minute,
      ctgstat[contigs[i].ctgstat], contigs[i].ctgIBC, contigs[i].ctgQs,
      contigs[i].high_score,contigs[i].avg_score,contigs[i].low_score, str);

      str1[0]=str2[0]='\0';
      if (contigs[i].noedit_chr) strcpy(str1,"NoAutoChr");
      if (contigs[i].noedit_pos) strcpy(str2,"NoAutoPos");
      fprintf(fpout, "Chr_remark \"%s\" Pos %7.3f %s %s\n",
                 contigs[i].chr_msg, contigs[i].chr_pos, str1, str2);

    if (!spaceOnly(contigs[i].user_msg))
        fprintf(fpout, "User_remark \"%s\"\n",contigs[i].user_msg);
    if (!spaceOnly(contigs[i].trace_msg))
        fprintf(fpout, "Trace_remark \"%s\"\n",contigs[i].trace_msg);
  }

  /* write sequence files */
  fprintf(fpout,"\nSeqdata\n");
  for(pfiles = seq_info_files; pfiles != 0; pfiles = pfiles->next) 
  {
    switch (pfiles->type)
    {
        case FT_SEQ:
        fprintf(fpout,"SEQ_INFO %s\n",pfiles->path);
        break;
        case FT_BES:
        fprintf(fpout,"BES_MAP %s\n",pfiles->path);
        break;
        case FT_BSS:
        fprintf(fpout,"SEQ_BSS %s\n",pfiles->path);
        break;
    }
  }

/************************************************************/

  fclose(fpout);
  fprintf(stderr,"...Done\n");
  sprintf(buf,"chmod -f 664 %s", file);
  system(buf);

  update = FALSE;
  if (savefpp) savefppdata();
  return 1;
}

/*************************************************************
                    DEF: spaceOnly
**************************************************************/
int spaceOnly(char *tmp)
{
int i;
   for (i=0; tmp[i]!='\0'; i++)
     if (tmp[i]!=' ') return 0;
   return 1;
}
/**************************************************************
                    DEF: formatdate
**************************************************************/
void formatdate(struct mytime *mytime, char *buf)
{
int new_year=0;
char mon[4], min[4], year[4];
char month[13][4]={"NaN", "jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"};

      if (mytime->month>0 && mytime->month<13)
            sprintf(mon,"%s",month[mytime->month]);
      else sprintf(mon,"NaN");

      if (mytime->minute<10)
             sprintf(min,"0%d",mytime->minute);
      else sprintf(min,"%d",mytime->minute);

      if (mytime->year!=0)
          new_year = mytime->year % 100;
      if (new_year<10) sprintf(year,"0%d",new_year);
      else sprintf(year,"%d",new_year);

      sprintf(buf, "%2d%s%s %2d:%s",mytime->day,mon,year,mytime->hour,min);
}
/****************************************************************
                    DEF: settime
****************************************************************/
void settime(struct mytime *mytime)
{
  struct tm *curr_time;
  time_t ltime;
  char buf[BUFSZ];

  if (time(&ltime) != -1) {
    curr_time = localtime(&ltime);
    if (!strftime(buf, BUFSZ, "%R %a %d %h %Y", curr_time))
      fprintf(stderr, "Warning: Not enough room for time stamp.");

    mytime->year = curr_time->tm_year;
    mytime->month = curr_time->tm_mon+1;
    mytime->day = curr_time->tm_mday;
    mytime->hour = curr_time->tm_hour;
    mytime->minute = curr_time->tm_min;
    update = TRUE;
  }
}

/***********************************************************
               DEF: getdatehead
************************************************************/
void getdatehead(char *out2)
{
  struct tm *curr_time;
  time_t ltime;
  struct passwd *uinfo;
  char buf[BUFSZ], Version[11];

  strcpy(Version,VERSION);
  if (time(&ltime) != -1) {
    curr_time = localtime(&ltime);
    if (!strftime(buf, BUFSZ, "%R %a %d %h %Y", curr_time))
      fprintf(stderr, "Warning: Not enough room for time stamp.");
  }
  else buf[0] = '\0';
  /* solaris and sgi give null on uinfo */
  uinfo = (struct passwd *) getpwuid((uid_t) geteuid());
  if (uinfo == NULL) sprintf(out2,"%s  Date: %s", Version,buf);
  else sprintf(out2,"%s  Date: %s  User: %s",
               Version,buf,uinfo->pw_name);
}
